using DevExpress.Blazor;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Blazor.Services;
using DevExpress.ExpressApp.SystemModule;
using EasyXaf.LowCode.WorkflowEditors.Models;
using EasyXaf.LowCode.WorkflowEditors.UndoManagers;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

namespace EasyXaf.LowCode.WorkflowEditors.Nodes;

public partial class NodeDetailComponent : IDisposable
{
    private View _nodeView;

    private DxTextBox CaptionTextBox { get; set; }

    private DxMemo CommentMemo { get; set; }

    private string CaptionValue { get; set; }

    private string CommentValue { get; set; }

    private bool CaptionEditing { get; set; }

    private bool CommentEditing { get; set; }

    private bool IsReadOnly
    {
        get => WorkflowMode >= WorkflowMode.Debug;
    }

    [CascadingParameter]
    public WorkflowMode WorkflowMode { get; set; }

    [CascadingParameter]
    public IUndoManager UndoManager { get; set; }

    [Parameter]
    public INode Node { get; set; }

    [Parameter]
    public EventCallback EnterContainer { get; set; }

    [Parameter]
    public EventCallback<MouseEventArgs> ShowNodeMenu { get; set; }

    [Inject]
    public IXafApplicationProvider ApplicationProvider { get; set; }

    private void ProcessTextBoxKeyDown(KeyboardEventArgs e)
    {
        if (e.Code == "Escape")
        {
            if (CaptionEditing)
            {
                CancelEditCaption();
            }
            else if (CommentEditing)
            {
                CancelEditComment();
            }
        }
        else if (e.Code == "Enter" || e.Code == "NumpadEnter")
        {
            if (CaptionEditing)
            {
                EndEditCaption();
            }
        }
    }

    private void BeginEditCaption()
    {
        if (!IsReadOnly)
        {
            CaptionValue = Node.Caption;
            CaptionEditing = true;
        }
    }

    private void CancelEditCaption()
    {
        CaptionEditing = false;
    }

    private void EndEditCaption()
    {
        if (!string.IsNullOrWhiteSpace(CaptionValue))
        {
            if (Node.Caption != CaptionValue)
            {
                UndoManager.ChangeNodeCaption(Node, CaptionValue);
            }
        }
        CaptionEditing = false;
    }

    public void BeginEditComment()
    {
        if (!IsReadOnly)
        {
            CommentValue = Node.Comment;
            CommentEditing = true;
        }
    }

    private void CancelEditComment()
    {
        CommentEditing = false;
    }

    private void EndEditComment()
    {
        if (Node.Comment != CommentValue)
        {
            UndoManager.ChangeNodeComment(Node, CommentValue);
        }
        CommentEditing = false;
    }

    private void ChangeViewMode()
    {
        UndoManager.ChangeNodeViewMode(Node, NodeViewMode.Title);
    }

    private void DeleteComment()
    {
        UndoManager.ChangeNodeComment(Node, string.Empty);
    }

    protected override void OnInitialized()
    {
        base.OnInitialized();

        var application = ApplicationProvider.GetApplication();
        var objectSpace = application.CreateObjectSpace(Node.GetType());
        var viewId = application.GetDetailViewId(Node.GetType());
        _nodeView = application.CreateDetailView(objectSpace, viewId, true, Node);
        if (_nodeView.Model is IModelDetailViewDefaultFocusedItem model)
        {
            model.DefaultFocusedItem = null;
        }
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);

        if (CaptionEditing && CaptionTextBox != null)
        {
            await CaptionTextBox.FocusAsync();
        }
        else if (CommentEditing && CommentMemo != null)
        {
            await CommentMemo.FocusAsync();
        }
    }

    public void Dispose()
    {
        if (_nodeView != null)
        {
            _nodeView.Dispose();
            _nodeView = null;
        }
        GC.SuppressFinalize(this);
    }
}